package com.tarena.lbs.article.web.dao.repository;

import com.alibaba.fastjson2.JSON;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.tarena.lbs.pojo.content.entity.ArticleSearchEntity;
import com.tarena.lbs.pojo.content.query.ArticleQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.util.QueryBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Repository
@Slf4j
public class ArticleRepository {
    //es的客户端api
    @Autowired
    private RestHighLevelClient restHighLevelClient;
    @Autowired
    private ArticleESRepository esRepository;
    public List<ArticleSearchEntity> search(ArticleQuery repositoryQuery) {
        //1.搜索请求
        SearchRequest request = new SearchRequest("lbs_article");
        //2.请求参数
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        assembleSearchSource(repositoryQuery, sourceBuilder);
        request.source(sourceBuilder);
        //3.调用请求 解析响应
        List<ArticleSearchEntity> entities = null;
        try {
            SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            SearchHit[] hits = searchResponse.getHits().getHits();
            if (hits != null && hits.length > 0) {
                //检索结果非空
                entities = Arrays.stream(hits).map(hit->{
                    return JSON.parseObject(hit.getSourceAsString(),ArticleSearchEntity.class);
                }).collect(Collectors.toList());
            }
        }catch (Exception e){
            e.printStackTrace();
            //打印日志error
        }
        return entities;
    }

    private void assembleSearchSource(ArticleQuery repositoryQuery, SearchSourceBuilder sourceBuilder) {
        //根据repositoryQuery中非空属性 拼接bool查询条件的字条件 交给sourceBuilder
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        if(StringUtils.isNotEmpty(repositoryQuery.getArticleTitle())){
            //1. 文章标题非空 需要组织bool字条件 模糊查询 es中是相似度查询使用matchquery
            query.must(QueryBuilders.matchQuery("articleTitle",repositoryQuery.getArticleTitle()));
        }
        if(repositoryQuery.getArticleCategoryId()!=null){
            //2. 文章分类非空 相等查询termQuery
            query.must(QueryBuilders.termQuery("articleCategoryId",repositoryQuery.getArticleCategoryId()));
        }
        //3.标签非空 判断term相等
        if(StringUtils.isNotEmpty(repositoryQuery.getArticleLabel())){
            query.must(QueryBuilders.termQuery("articleLabel",repositoryQuery.getArticleLabel()));
        }
        //4.文章状态 list 但是参数只可能有一个元素 term
        if(CollectionUtils.isNotEmpty(repositoryQuery.getArticleStatus())&&repositoryQuery.getArticleStatus().size()==1){
            query.must(QueryBuilders.termQuery("articleStatus",repositoryQuery.getArticleStatus().get(0)));
        }
        //5.source非空 term 只有后台才关心source 前台手机小程序 不关心source
        if(repositoryQuery.getSource()!=null){
            query.must(QueryBuilders.termQuery("source",repositoryQuery.getSource()));
        }
        //7.userId非空 查询该用户的文章数据
        if(repositoryQuery.getUserId()!=null){
            query.must(QueryBuilders.termQuery("userId",repositoryQuery.getUserId()));
        }//8.范围查询rangeQuery startTime下限 endTime上限
        if(repositoryQuery.getUpdateStartTime()!=null){
            query.must(QueryBuilders.rangeQuery("updateTime").gte(repositoryQuery.getUpdateStartTime()));
        }
        if(repositoryQuery.getUpdateEndTime()!=null){
            query.must(QueryBuilders.rangeQuery("updateTime").lte(repositoryQuery.getUpdateEndTime()));
        }
        //9.地理位置查询 中心点 lat lon 半径 100公里
        if(StringUtils.isNotBlank(repositoryQuery.getLatitude())&&StringUtils.isNotBlank(repositoryQuery.getLongitude())){
            GeoDistanceQueryBuilder geoQuery = QueryBuilders.geoDistanceQuery("location");
            geoQuery.point(Double.valueOf(repositoryQuery.getLatitude()),Double.valueOf(repositoryQuery.getLongitude()));
            geoQuery.distance(100D, DistanceUnit.KILOMETERS);
            query.must(geoQuery);
        }
        sourceBuilder.query(query);
        log.info("当前封装的查询条件:{}",sourceBuilder);
    }

    public void save(ArticleSearchEntity entity) {
        esRepository.save(entity);
    }
}
